import logging
import logging.handlers
import threading
from typing import AnyStr, Optional


class Loggers(logging.Logger):
    _instance_lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if not hasattr(Loggers, "_instance"):
            with Loggers._instance_lock:
                if not hasattr(Loggers, "_instance"):
                    Loggers._instance = object.__new__(cls)
        return Loggers._instance

    def __init__(self, name: AnyStr, filename: Optional[AnyStr] = None):
        super(Loggers, self).__init__(name)
        self.filename = filename
        self._set_format()

    def _set_format(self):
        self._add_handlers()
        formatter = logging.Formatter('[%(levelname)s] [%(asctime)s] [%(filename)s:%(lineno)d] : %(message)s')
        for j in self.handlers:
            j.setFormatter(formatter)

    def _add_handlers(self):
        if not self.handlers:
            if self.filename:
                rotatingFileHandler = logging.handlers.RotatingFileHandler(filename=self.filename,
                                                                           maxBytes=1024 * 1024 * 50,
                                                                           backupCount=5)
                self.addHandler(rotatingFileHandler)

            console = logging.StreamHandler()
            self.addHandler(console)


